package org.jeecg.modules.system.service.impl;

import java.io.Serializable;
import java.util.*;

import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.SsoUtil;
import org.jeecg.common.util.StringUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.*;
import org.jeecg.modules.system.mapper.*;
import org.jeecg.modules.system.service.ISysUserRoleService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.vo.SysUserRoleScope;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import lombok.extern.slf4j.Slf4j;

/**
 * 用户表 服务实现类
 * @Author: scott
 * @Date: 2018-12-20
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
	
	@Autowired
	private SysUserMapper sysUserMapper;
	@Autowired
	private SysUserPositionMapper sysUserPositionMapper;
	@Autowired
	private SysPermissionMapper sysPermissionMapper;
	@Autowired
	private SysUserRoleMapper sysUserRoleMapper;
	@Autowired
	private SysUserDepartMapper sysUserDepartMapper;
	@Autowired
	private ISysBaseAPI sysBaseAPI;
	@Autowired
	private SysDepartMapper sysDepartMapper;

	@Override
	public SysUser getUserByName(String username) {
		return sysUserMapper.getUserByName(username);
	}

	
	@Override
	@Transactional
	public void addUserWithRole(SysUser user, String roles) {
		this.save(user);
		if(oConvertUtils.isNotEmpty(roles)) {
			String[] arr = roles.split(",");
			for (String roleId : arr) {
				SysUserRole userRole = new SysUserRole(user.getId(), roleId);
				sysUserRoleMapper.insert(userRole);
			}
		}
	}

	@Override
	@CacheEvict(value= CacheConstant.LOGIN_USER_RULES_CACHE, allEntries=true)
	@Transactional
	public void editUserWithRole(SysUser user, String roles) {
		this.updateById(user);
		//先删后加
		sysUserRoleMapper.delete(new QueryWrapper<SysUserRole>().lambda().eq(SysUserRole::getUserId, user.getId()));
		if(oConvertUtils.isNotEmpty(roles)) {
			String[] arr = roles.split(",");
			for (String roleId : arr) {
				SysUserRole userRole = new SysUserRole(user.getId(), roleId);
				sysUserRoleMapper.insert(userRole);
			}
		}
	}


	@Override
	public List<String> getRole(String username) {
		return sysUserRoleMapper.getRoleByUserName(username);
	}
	
	/**
	 * 通过用户名获取用户角色集合
	 * @param username 用户名
     * @return 角色集合
	 */
	@Override
	@Cacheable(value = CacheConstant.LOGIN_USER_RULES_CACHE,key = "'Roles_'+#username")
	public Set<String> getUserRolesSet(String username) {
		// 查询用户拥有的角色集合
		List<String> roles = sysUserRoleMapper.getRoleByUserName(username);
		log.info("-------通过数据库读取用户拥有的角色Rules------username： " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
		return new HashSet<>(roles);
	}


	@Override
	@Cacheable(value = CacheConstant.LOGIN_USER_RULES_CACHE,key = "'RolesType_'+#userId")
	public Set<String> getUserRoleTypeSet(String userId) {
		// 查询用户拥有的角色集合
		List<String> roleTypes = sysUserRoleMapper.getRoleByUserId(userId);
		log.info("-------通过数据库读取用户拥有的角色类型------userId： " + userId + ",Roles size: " + (roleTypes == null ? 0 : roleTypes.size()));
		return new HashSet<>(roleTypes);
	}

	/**
	 * 通过用户名获取用户权限集合
	 *
	 * @param username 用户名
	 * @return 权限集合
	 */
	@Override
	@Cacheable(value = CacheConstant.LOGIN_USER_RULES_CACHE,key = "'Permissions_'+#username")
	public Set<String> getUserPermissionsSet(String username) {
		Set<String> permissionSet = new HashSet<>();
		List<SysPermission> permissionList = sysPermissionMapper.queryByUser(username,null);
		for (SysPermission po : permissionList) {
//			// TODO URL规则有问题？
//			if (oConvertUtils.isNotEmpty(po.getUrl())) {
//				permissionSet.add(po.getUrl());
//			}
			if (oConvertUtils.isNotEmpty(po.getPerms())) {
				permissionSet.add(po.getPerms());
			}
		}
		log.info("-------通过数据库读取用户拥有的权限Perms------username： "+ username+",Perms size: "+ (permissionSet==null?0:permissionSet.size()) );
		return permissionSet;
	}

	@Override
	public SysUserCacheInfo getCacheUser(String username) {
		SysUserCacheInfo info = new SysUserCacheInfo();
		info.setOneDepart(true);
//		SysUser user = sysUserMapper.getUserByName(username);
//		info.setSysUserCode(user.getUsername());
//		info.setSysUserName(user.getRealname());
		

		LoginUser user = sysBaseAPI.getUserByName(username);
		if(user!=null) {
			info.setSysUserCode(user.getUsername());
			info.setSysUserName(user.getRealname());
			info.setSysOrgCode(user.getOrgCode());
		}
		
		//多部门支持in查询
		List<SysDepart> list = sysDepartMapper.queryUserDeparts(user.getId());
		List<String> sysMultiOrgCode = new ArrayList<String>();
		if(list==null || list.size()==0) {
			//当前用户无部门
			//sysMultiOrgCode.add("0");
		}else if(list.size()==1) {
			sysMultiOrgCode.add(list.get(0).getOrgCode());
		}else {
			info.setOneDepart(false);
			for (SysDepart dpt : list) {
				sysMultiOrgCode.add(dpt.getOrgCode());
			}
		}
		info.setSysMultiOrgCode(sysMultiOrgCode);
		
		return info;
	}

	// 根据部门Id查询
	@Override
	public IPage<SysUser> getUserByDepId(Page<SysUser> page, String departId,String username) {
		return sysUserMapper.getUserByDepId(page, departId,username);
	}


	// 根据角色Id查询
	@Override
	public IPage<SysUser> getUserByRoleId(Page<SysUser> page, String roleId, String username) {
		return sysUserMapper.getUserByRoleId(page,roleId,username);
	}


	@Override
	public void updateUserDepart(String username,String orgCode) {
		baseMapper.updateUserDepart(username, orgCode);
	}

	@Override
	public SysUser getUserByPhone(String phone) {
		return sysUserMapper.getUserByPhone(phone);
	}


	@Override
	public SysUser getUserByEmail(String email) {
		return sysUserMapper.getUserByEmail(email);
	}

	@Override
	@Transactional
	public void addUserWithDepart(SysUser user, String selectedParts) {
//		this.save(user);  //保存角色的时候已经添加过一次了
		if(oConvertUtils.isNotEmpty(selectedParts)) {
			String[] arr = selectedParts.split(",");
			for (String deaprtId : arr) {
				SysUserDepart userDeaprt = new SysUserDepart(user.getId(), deaprtId);
				sysUserDepartMapper.insert(userDeaprt);
			}
		}
	}


	@Override
	@Transactional
	@CacheEvict(value="loginUser_cacheRules", allEntries=true)
	public void editUserWithDepart(SysUser user, String departs) {
		this.updateById(user);  //更新角色的时候已经更新了一次了，可以再跟新一次
		//先删后加
		sysUserDepartMapper.delete(new QueryWrapper<SysUserDepart>().lambda().eq(SysUserDepart::getUserId, user.getId()));
		if(oConvertUtils.isNotEmpty(departs)) {
			String[] arr = departs.split(",");
			for (String departId : arr) {
				SysUserDepart userDepart = new SysUserDepart(user.getId(), departId);
				sysUserDepartMapper.insert(userDepart);
			}
		}
	}


	/**
	 * 校验用户是否有效
	 * @param sysUser
	 * @return
	 */
	@Override
	public Result<?> checkUserIsEffective(SysUser sysUser) {
		Result<?> result = new Result<Object>();
		//情况1：根据用户信息查询，该用户不存在
		if (sysUser == null) {
			result.error500("该用户不存在，请注册");
			sysBaseAPI.addLog("用户登录失败，用户不存在！", CommonConstant.LOG_TYPE_1, null);
			return result;
		}
		//情况2：根据用户信息查询，该用户已注销
		if (CommonConstant.DEL_FLAG_1.toString().equals(sysUser.getDelFlag())) {
			sysBaseAPI.addLog("用户登录失败，用户名:" + sysUser.getUsername() + "已注销！", CommonConstant.LOG_TYPE_1, null);
			result.error500("该用户已注销");
			return result;
		}
		//情况3：根据用户信息查询，该用户已冻结
		if (CommonConstant.USER_FREEZE.equals(sysUser.getStatus())) {
			sysBaseAPI.addLog("用户登录失败，用户名:" + sysUser.getUsername() + "已冻结！", CommonConstant.LOG_TYPE_1, null);
			result.error500("该用户已冻结");
			return result;
		}
		//情况4：根据用户信息查询,该用户未开通
		if (CommonConstant.USER_NO_AVAILABLE == sysUser.getStatus()){
			sysBaseAPI.addLog("用户登录失败，用户名:" + sysUser.getUsername() + "未开通账号！", CommonConstant.LOG_TYPE_1, null);
			result.error500("该用户未开通账号");
			return result;
		}
		return result;
	}



	@Override
	@Transactional
	public void saveMain(SysUser sysUser, List<SysUserPosition> sysUserPositionList,List<SysUserRole> sysUserRoleList) {
		sysUserMapper.insert(sysUser);
		for(SysUserPosition entity:sysUserPositionList) {
			//外键设置
			entity.setUserId(sysUser.getId());
			sysUserPositionMapper.insert(entity);
		}
		for(SysUserRole entity:sysUserRoleList) {
			//外键设置
			entity.setUserId(sysUser.getId());
			sysUserRoleMapper.insert(entity);
		}
	}

	@Override
	@Transactional
	public void updateMain(SysUser sysUser,List<SysUserPosition> sysUserPositionList,List<SysUserRole> sysUserRoleList) {
		sysUserMapper.updateById(sysUser);

		//1.先删除子表数据
		sysUserPositionMapper.deleteByMainId(sysUser.getId());
		sysUserRoleMapper.deleteByMainId(sysUser.getId());

		//2.子表数据重新插入
		for(SysUserPosition entity:sysUserPositionList) {
			//外键设置
			entity.setUserId(sysUser.getId());
			sysUserPositionMapper.insert(entity);
		}
		for(SysUserRole entity:sysUserRoleList) {
			//外键设置
			entity.setUserId(sysUser.getId());
			sysUserRoleMapper.insert(entity);
		}
	}

	@Override
	@Transactional
	public void delMain(String id) {
		sysUserPositionMapper.deleteByMainId(id);
		sysUserRoleMapper.deleteByMainId(id);
		sysUserMapper.deleteById(id);
	}

	@Override
	@Transactional
	public void delBatchMain(Collection<? extends Serializable> idList) {
		for(Serializable id:idList) {
			sysUserPositionMapper.deleteByMainId(id.toString());
			sysUserRoleMapper.deleteByMainId(id.toString());
			sysUserMapper.deleteById(id);
		}
	}

	@Override
	public String selectDepart(String userId ) {
		return  sysUserMapper.selectDepart(userId);
	}

	@Override
	public List<SysUser> getUsersByProjectId(String projectId) {
		String departIds = sysUserMapper.getDepartIds(projectId);
		if(StringUtils.isEmpty(departIds)){
			return null;
		}
		departIds = departIds.replaceAll(",,",",");
		List<String> ids = Arrays.asList(departIds.split(","));
		if(ids.size() > 0){
			return sysUserMapper.getUsersByDeparts(ids);
		}
		return null;
	}

	@Override
	public List<SysUser> findPage(Page<SysUser> page,SysUser sysUser) {
		 List<SysUser> sysUsers = sysUserMapper.selectAllRecord(page,sysUser);
		 return sysUsers;
	}

	@Override
	public List<SysUser> findPageByPosition(Page<SysUser> page,SysUser sysUser) {
		List<SysUser> sysUsers = sysUserMapper.selectAllRecordByPosition(page,sysUser);
		return sysUsers;
	}

	@Override
	public List<SysDepart> getUserByDepardId(String depardId){
		return sysUserMapper.getUserByDepardId(depardId);
	}

	@Override
	public SysUser getUserByLoginName(String userName) {
		return sysUserMapper.getUserByLoginName(userName);
	}

	@Override
	public List<SysUser> findAddressBookList(SysUser sysUser) {
		return sysUserMapper.findAddressBookList(sysUser);
	}

	@Override
	public List<SysUser> findChildUserByDepartId(String id) {
		return sysUserMapper.findChildUserByDepartId(id);
	}

	@Override
	public void updateBatchById(List<SysUser> sysUserList) {
		sysUserMapper.updateBatchById(sysUserList);
	}

	@Override
	public void autoAccount(String userId, LoginUser loginUser) {
		sysUserMapper.autoAccount(userId,loginUser.getId());
	}

	@Override
	public List<SysUser> findServerPage(Page<SysUser> page, SysUser sysUser) {
		return sysUserMapper.findServerPage(page,sysUser);
	}

	@Override
	public void serverSave(SysUser sysUser) {
		String userId = SsoUtil.getLoginUser().getId();
		sysUser.setCreateBy(userId);
		sysUser.setCreateTime(new Date());
		sysUser.setUpdateBy(userId);
		sysUser.setUpdateTime(new Date());
		sysUser.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
		sysUserMapper.serverSave(sysUser);
	}

	@Override
	public int getServerCountByAccount(String adminAccount) {
		return sysUserMapper.getServerCountByAccount(adminAccount);
	}

	@Override
	public void serverUpdateByName(SysUser sysUser, String adminAccount) {
		sysUserMapper.serverUpdateByName(sysUser,adminAccount);
	}


}
